/*
* @file    :gc.c
* @module  :GC
* @author  :LingFengLu
* @date    :2023-06-06
*/

#include "gc.h"
#include "drv.h"
#include "lib_string.h"
#include "lib_checksum.h"
//Constant definition    宏定义

#define GC_RESET_PIN                    GPIO_CHANNEL(PORT_A,PIN10)
#define GC_WAKEUP_PIN                   GPIO_CHANNEL(PORT_A,PIN9)
#define GC_SHELF_MODE_QUIT_PIN          GPIO_CHANNEL(PORT_A,PIN8)
#define GC_HANDSHAKE_OUT_PIN            GPIO_CHANNEL(PORT_A,PIN1)
#define GC_HANDSHAKE_IN_PIN             GPIO_CHANNEL(PORT_A,PIN0)


#define STATE_IDLE                      0
#define STATE_HEADER                    1
#define STATE_DATA                      2
#define STATE_ESCAPE                    3

#define HEADER_LENGTH                   2
#define FRAME_HEADER                    ('+')
#define FRAME_ESCAPE                    ('/')


#define STATE_IDLE                      0
#define STATE_HEADER                    1
#define STATE_DATA                      2
#define STATE_ESCAPE                    3

#define MAX_TX_FRAME_SIZE               16
#define MAX_RX_FRAME_SIZE               16


typedef struct
{
	uint8 *data;
	uint32 size;
} frame_t;
//Global variable definition    全局变量定义


//Private variable definition    私有变量定义
static bool m_b_RxFinished = false;
static uint8 m_t_DataBuffer[MAX_RX_FRAME_SIZE];
static uint8 m_t_DataBufferBackup[MAX_RX_FRAME_SIZE];
static frame_t m_RxFrame = {m_t_DataBuffer,0};
static frame_t m_RxFrameBackup = {m_t_DataBufferBackup,0};
//Private function declaration   私有函数申明
static void Gc_ShelfModeQuit(void);
static uint Gc_Open(void);
static void Gc_Close(void);
static void Gc_ShelfModeQuit(void);
static void Gc_Write
(
uint8 * u8p_Data,
uint16 u16_Len
);
static uint Gc_Read
(
uint8 * u8p_Data,
uint16  * u16p_Len
);







//Public function definition   公共函数定义

void Gc_Init(void)
{
	DrvGpio_Set(GC_RESET_PIN,MODE_OUTPUT_NO,1);
	DrvGpio_Set(GC_SHELF_MODE_QUIT_PIN,MODE_OUTPUT_NO,0);
	DrvGpio_Set(GC_WAKEUP_PIN,MODE_OUTPUT_NO,0);
	DrvGpio_Set(GC_HANDSHAKE_OUT_PIN,MODE_OUTPUT_NO,0);
	DrvGpio_Set(GC_HANDSHAKE_IN_PIN,MODE_INPUT_NO,0);
}

uint Gc_GetIMeas
(
int16 *i16p_I1, 
int16 *i16p_I2, 
int16 *i16p_Vc
)
{
	if (Gc_Open() == FUNCTION_OK)
	{
		uint8 u8_Buffer[6] = {0x01, 0x01};
		Gc_Write(u8_Buffer, 2);
		uint16 u16_Len;
		uint ui_Result = Gc_Read(u8_Buffer, &u16_Len);
		Gc_Close();
		if (ui_Result == FUNCTION_OK)
		{
			*i16p_I1 = *(int16*)(u8_Buffer    );
			*i16p_I2 = *(int16*)(u8_Buffer + 2);
			*i16p_Vc = *(int16*)(u8_Buffer + 4);
			return FUNCTION_OK;
		}
		else
		{
			Gc_Reset();
			return FUNCTION_FAIL;
		}
	}
	else
	{
		Gc_Reset();
		return FUNCTION_FAIL;
	}
}

uint Gc_GetIMeasFilt
(
int16 *i16p_I1, 
int16 *i16p_I2, 
int16 *i16p_Vc
)
{
	if (Gc_Open() == FUNCTION_OK)
	{
		uint8 u8_Buffer[6] = {0x01, 0x02};
		Gc_Write(u8_Buffer, 2);
		uint16 u16_Len;
		uint ui_Result = Gc_Read(u8_Buffer, &u16_Len);
		Gc_Close();
		if (ui_Result == FUNCTION_OK)
		{
			*i16p_I1 = *(int16*)(u8_Buffer    );
			*i16p_I2 = *(int16*)(u8_Buffer + 2);
			*i16p_Vc = *(int16*)(u8_Buffer + 4);
			return FUNCTION_OK;
		}
		else
		{
			Gc_Reset();
			return FUNCTION_FAIL;
		}
	}
	else
	{
		Gc_Reset();
		return FUNCTION_FAIL;
	}
}

uint Gc_GetZMeas
(
int16 *i16p_Zreal, 
int16 *i16p_Zimag
)
{
	if (Gc_Open() == FUNCTION_OK)
	{
		uint8 u8_Buffer[6] = {0x01, 0x03};
		Gc_Write(u8_Buffer, 2);
		uint16 u16_Len;
		uint ui_Result = Gc_Read(u8_Buffer, &u16_Len);
		Gc_Close();
		if (ui_Result == FUNCTION_OK)
		{
			*i16p_Zreal = *(int16*)(u8_Buffer    );
			*i16p_Zimag = *(int16*)(u8_Buffer + 2);
			return FUNCTION_OK;
		}
		else
		{
			Gc_Reset();
			return FUNCTION_FAIL;
		}
	}
	else
	{
		Gc_Reset();
		return FUNCTION_FAIL;
	}
}

uint Gc_SetBias
(
uint16 u16_Bias
)
{
	if (Gc_Open() == FUNCTION_OK)
	{
		uint8 u8_Buffer[3] = {0x02, 0x01, u16_Bias};
		Gc_Write(u8_Buffer, 3);
		uint16 u16_Len;
		uint ui_Result = Gc_Read(u8_Buffer, &u16_Len);
		Gc_Close();
		if (ui_Result == FUNCTION_OK)
		{
			return (u8_Buffer[0] == FUNCTION_OK && u16_Len == 1);
		}
		else
		{
			Gc_Reset();
			return FUNCTION_FAIL;
		}
	}
	else
	{
		Gc_Reset();
		return FUNCTION_FAIL;
	}
}

uint Gc_DoZMeas(void)
{
	if (Gc_Open() == FUNCTION_OK)
	{
		uint8 u8_Buffer[3] = {0x02, 0x02};
		Gc_Write(u8_Buffer, 2);
		uint16 u16_Len;
		uint ui_Result = Gc_Read(u8_Buffer, &u16_Len);
		Gc_Close();
		if (ui_Result == FUNCTION_OK)
		{
			return (u8_Buffer[0] == FUNCTION_OK && u16_Len == 1);
		}
		else
		{
			Gc_Reset();
			return FUNCTION_FAIL;
		}
	}
	else
	{
		Gc_Reset();
		return FUNCTION_FAIL;
	}
}

uint Gc_SetMaxBias
(
uint16 u16_maxBias
)
{
	if (Gc_Open() == FUNCTION_OK)
    {
        uint8 u8_Buffer[3] = {0x0F, 0x01, u16_maxBias};
        Gc_Write(u8_Buffer, 3);
        uint16 u16_Len;
        uint ui_Result = Gc_Read(u8_Buffer, &u16_Len);
        Gc_Close();
        if (ui_Result == FUNCTION_OK)
        {
            return (u8_Buffer[0] == FUNCTION_OK && u16_Len == 1);
        }
        else
        {
            Gc_Reset();
            return FUNCTION_FAIL;
        }
    }
    else
    {
        Gc_Reset();
        return FUNCTION_FAIL;
    }
}

uint Gc_SetImeasTrimming
(
uint8 u8_channel, 
sint16 s16_imeasZero, 
sint16 s16_imeasScale
)
{
	if (Gc_Open() == FUNCTION_OK)
    {
        uint8 u8_Buffer[7] = {0x0F, 0x02};
        u8_Buffer[2] = u8_channel, 
        *((sint16*)(u8_Buffer+3)) = s16_imeasZero;
        *((sint16*)(u8_Buffer+5)) = s16_imeasScale;
        Gc_Write(u8_Buffer, 7);
        uint16 u16_Len;
        uint ui_Result = Gc_Read(u8_Buffer, &u16_Len);
        Gc_Close();
        if (ui_Result == FUNCTION_OK)
        {
            return (u8_Buffer[0] == FUNCTION_OK && u16_Len == 1);
        }
        else
        {
            Gc_Reset();
            return FUNCTION_FAIL;
        }
    }
    else
    {
        Gc_Reset();
        return FUNCTION_FAIL;
    }
}

void Gc_Reset(void)
{
	Gc_ShelfModeQuit();
    DrvGpio_Set(GC_RESET_PIN,MODE_OUTPUT_NO,0);
    Drv_DelayMs(5);
    DrvGpio_Set(GC_RESET_PIN,MODE_OUTPUT_NO,1);
}
void DrvUart_RX_Callback(void)
{
	uint8 u8_Data;
   static uint8 u8_HeadCount = 0;
   static uint8 u8_State = STATE_IDLE;

   u8_Data = LL_USART_ReceiveData8(USART1);
   LOG_INFO("%d",u8_Data);
   switch (u8_State)
   {
   case STATE_IDLE:
       if (u8_Data == FRAME_HEADER)
       {
           u8_HeadCount++;
           u8_State = STATE_HEADER;
       }
       break;
   case STATE_HEADER:
       if (u8_Data == FRAME_HEADER)
       {
           u8_HeadCount++;
       }
       else
       {
           if (u8_HeadCount >= HEADER_LENGTH)
           {
               u8_HeadCount = 0;
               if (u8_Data == FRAME_ESCAPE)
               {
                   u8_State = STATE_ESCAPE;
               }
               else
               {
                   if (m_RxFrame.size < MAX_RX_FRAME_SIZE)
                   {
                       m_t_DataBuffer[m_RxFrame.size++] = u8_Data;
                   }
                   u8_State = STATE_DATA;
               }
           }
           else
           {
               u8_State = STATE_IDLE;
           }
       }
       break;
   case STATE_DATA:
       if (u8_Data == FRAME_HEADER)
       {
           u8_HeadCount++;
           if (u8_HeadCount >= HEADER_LENGTH)
           {
               Lib_Memcpy(m_RxFrameBackup.data, m_RxFrame.data, m_RxFrame.size);
               m_RxFrameBackup.size = m_RxFrame.size;
               m_b_RxFinished = true;
               u8_HeadCount = 0;
               u8_State = STATE_IDLE;
               m_RxFrame.size = 0;
           }
       }
       else
       {
           u8_HeadCount = 0;
           if (u8_Data == FRAME_ESCAPE)
           {
               u8_State = STATE_ESCAPE;
           }
           else
           {
               if (m_RxFrame.size < MAX_RX_FRAME_SIZE)
               {
                   m_t_DataBuffer[m_RxFrame.size++] = u8_Data;
               }
           }
       }
       break;
   case STATE_ESCAPE:
       if (m_RxFrame.size < MAX_RX_FRAME_SIZE)
       {
           m_t_DataBuffer[m_RxFrame.size++] = u8_Data;
       }
       u8_State = STATE_DATA;
       break;
   }

}


//Private function definition   私有函数定义
static uint Gc_Open(void)
{
	
	uint32 u32_Count = 0;
	DrvGpio_Set(GC_HANDSHAKE_OUT_PIN,MODE_OUTPUT_NO,1);
	Drv_DelayMs(2);
	DrvGpio_Set(GC_WAKEUP_PIN,MODE_OUTPUT_NO,1);
	while (DrvGpio_InGet(GC_HANDSHAKE_IN_PIN) != 0)
	{
		Drv_DelayMs(1);
		u32_Count ++;
		if(u32_Count > 32)
		{
			DrvGpio_Set(GC_HANDSHAKE_OUT_PIN,MODE_OUTPUT_NO,0);
			DrvGpio_Set(GC_WAKEUP_PIN,MODE_OUTPUT_NO,0);
			return FUNCTION_FAIL;
		}
	}
	DrvUart_Init(DRV_UART_DEVICE_ID_2) ;
	return FUNCTION_OK;
}

static void Gc_Close(void)
{
	DrvUart_DeInit(DRV_UART_DEVICE_ID_2);
	DrvGpio_Set(GC_HANDSHAKE_OUT_PIN,MODE_OUTPUT_NO,0);
	DrvGpio_Set(GC_WAKEUP_PIN,MODE_OUTPUT_NO,0);
}

static void Gc_ShelfModeQuit(void)
{
	DrvGpio_Set(GC_SHELF_MODE_QUIT_PIN,MODE_OUTPUT_NO,1);
    	Drv_DelayMs(10);
   	DrvGpio_Set(GC_SHELF_MODE_QUIT_PIN,MODE_OUTPUT_NO,0);
}

static void Gc_Write
(
uint8 * u8p_Data,
uint16 u16_Len
)
{
	uint8 u8_Value;
    uint8 i;

    u8_Value = FRAME_HEADER;
    for (i = 0; i < HEADER_LENGTH; i++)
    {
        DrvUart_SendByte(DRV_UART_DEVICE_ID_2 ,u8_Value);
    }
      
    for (i = 0; i < u16_Len; i++)
    {
        uint8 *u8p_Value = u8p_Data + i;
        if (*u8p_Value == FRAME_HEADER || *u8p_Value == FRAME_ESCAPE)
        {
            u8_Value = FRAME_ESCAPE;
            DrvUart_SendByte(DRV_UART_DEVICE_ID_2 ,u8_Value);
         
        }   
        DrvUart_SendByte(DRV_UART_DEVICE_ID_2 ,*u8p_Value);
      
    }

    uint8 u8_Checksum = LibChecksum_GetChecksum8Bit(u8p_Data, u16_Len);
    if (u8_Checksum == FRAME_HEADER || u8_Checksum == FRAME_ESCAPE)
    {
        u8_Value = FRAME_ESCAPE;
        DrvUart_SendByte(DRV_UART_DEVICE_ID_2 ,u8_Value);
       
    }
    DrvUart_SendByte(DRV_UART_DEVICE_ID_2 ,u8_Checksum);
  
    u8_Value = FRAME_HEADER;
    for (i = 0; i < HEADER_LENGTH; i++)
        DrvUart_SendByte(DRV_UART_DEVICE_ID_2 ,u8_Value);
      
    DrvUart_WaitSendFinish(DRV_UART_DEVICE_ID_2);
	
	
}

static uint Gc_Read
(
uint8 * u8p_Data,
uint16  * u16p_Len
)
{
	m_b_RxFinished = false;
	uint32 u32_Count = 0;
	while(m_b_RxFinished != true)
	{
		Drv_DelayMs(1);
		u32_Count++;
		if (u32_Count > 128)
		{
			m_b_RxFinished = true;
			return FUNCTION_FAIL;
		}
	}
	if(m_RxFrameBackup.data[m_RxFrameBackup.size-1] != LibChecksum_GetChecksum8Bit(m_RxFrameBackup.data, m_RxFrameBackup.size-1))
		return FUNCTION_FAIL;
	m_RxFrameBackup.size--;
	Lib_Memcpy(u8p_Data, m_RxFrameBackup.data, m_RxFrameBackup.size);
	*u16p_Len = m_RxFrameBackup.size;
	return FUNCTION_OK;
}
